/**
 *	---------------------------------------------------------------------------
 *	COMP 6231/FALL 2013
 *	Assignment - 02
 *	@author Talha Rahman (1296884)
 *	---------------------------------------------------------------------------
 *	This class processes each incoming UDP request to the server {@link StationServer}.
 *	This class extends the Thread class and runs concurrently - hence processing each
 *	UDP request in parallel. 
 *	  
 */
package ca.concordia.comp6231.udp;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import ca.concordia.comp6231.record.CriminalRecord;
import ca.concordia.comp6231.record.MissingRecord;
import ca.concordia.comp6231.record.Record;
import ca.concordia.comp6231.server.StationServer;
import ca.concordia.comp6231.server.StationServerCORBA;

public class UDPServiceRequestProcessor extends Thread {
	private StationServerCORBA corbaServer;
	private String responseString;
	private DatagramSocket socket;
	private DatagramPacket request;
	
	String functionName1 = "getRecordCount";
	String functionName2 = "transferRecord";
	String functionName3 = "createCRecord";
	String functionName4 = "createMRecord";
	String functionName5 = "editRecord";
	
	String functionName6 = "getRecordCountForCurrent";
		
	public UDPServiceRequestProcessor(StationServerCORBA corbaServer, DatagramSocket socket, DatagramPacket request) {
		this.corbaServer = corbaServer;
		this.socket = socket;
		this.request = request;
	}

	@Override
	public void run() {
		String requestString = new String(request.getData());
		System.out.println("The request string is : " + requestString);
		
		Map<String, String> params = processRequestString(requestString);
		System.out.println(params);
		
		if (params.get("functionName").equals(functionName1) ) {
			responseString = getRecordCountString(corbaServer, params);
		}else if(params.get("functionName").equals(functionName2)){
			responseString = functionName2;
		} else if (params.get("functionName").equals(functionName3)) {
			responseString = createCRecord(params);
		} else if (params.get("functionName").equals(functionName4)) {
			responseString = createMRecord(params);
		} else if (params.get("functionName").equals(functionName5)) {
			responseString = editRecord(params);
		} else if (params.get("functionName").equals(functionName6)) {
			responseString = getRecordCountForCurrent(corbaServer, params);
		}else{
			responseString = "message:failure,data:Invalid Request";
		}

		DatagramPacket reply = new DatagramPacket(responseString.getBytes(),
				responseString.length(), request.getAddress(),
				request.getPort());

		try {
			socket.send(reply);
		} catch (SocketException e) {
			System.out.println("Socket error: " + e.getMessage());
		} catch (IOException e) {
			System.out.println("IO error: " + e.getMessage());
		}
	}
	
	private String getRecordCountString(StationServerCORBA corbaServer, Map<String, String> recordParamMap) {
		String badgeID = recordParamMap.get("badgeID");
		
		String response = "";
		try {
			response = "message:success,data:" + corbaServer.getRecordCounts(badgeID);
		} catch (Exception e) {
			response = "message:failure";
		}

		return response;
	}
	
	private String getRecordCountForCurrent(StationServerCORBA corbaServer, Map<String, String> recordParamMap) {
		String badgeID = recordParamMap.get("badgeID");
		
		String response = "";
		try {
			response = "message:success,data:" + corbaServer.getServerName() + ":" + corbaServer.getRecordCountForCurrentServer();
		} catch (Exception e) {
			response = "message:failure";
		}

		return response;
	}
	
	private String createCRecord(Map<String, String> recordParamMap) {
		
		String firstLetterOfLastName = "";
		
		Record record = null;
		String ID = corbaServer.generateID("CR");
		String fName = recordParamMap.get("fName");
		String lName = recordParamMap.get("lName");
		String crimeDesc = recordParamMap.get("crimeDesc");
		String status = recordParamMap.get("status");
		
		record = new CriminalRecord(ID, fName, lName, crimeDesc, status);
		firstLetterOfLastName = lName.substring(0, 1).toUpperCase();
		
		String response = "";
		try {
			corbaServer.recordStore.addNewRecord(firstLetterOfLastName.charAt(0), record);
			response = "message:success,data:" + record;
		} catch (Exception e) {
			response = "message:failure,data:" + record;
		}
		
		return response;
	}
	
	private String createMRecord(Map<String, String> recordParamMap) {
			
			String firstLetterOfLastName = "";
			
			Record record = null;
			String ID = corbaServer.generateID("MR");
			String fName = recordParamMap.get("fName");
			String lName = recordParamMap.get("lName");
			String crimeDesc = recordParamMap.get("crimeDesc");
			String status = recordParamMap.get("status");
			String address = recordParamMap.get("address");
			String lastDate = recordParamMap.get("lastDate");
			String lastLocation = recordParamMap.get("lastLocation");
			
			record = new MissingRecord(ID, fName, lName, crimeDesc, address, lastDate, lastLocation, status);
			firstLetterOfLastName = lName.substring(0, 1).toUpperCase();
			
			String response = "";
			try {
				corbaServer.recordStore.addNewRecord(firstLetterOfLastName.charAt(0), record);
				response = "message:success,data:" + record;
			} catch (Exception e) {
				response = "message:failure,data:" + record;
			}
			
			return response;
	}
	
	private String editRecord(Map<String, String> recordParamMap) {
		
		String recordID = recordParamMap.get("recordID");
		String lName = recordParamMap.get("lName");
		String newStatus = recordParamMap.get("newStatus");
		String badgeID = recordParamMap.get("badgeID");
		
		String response = "";
		try {
			corbaServer.editRecord(lName, recordID, newStatus, badgeID);
			response = "message:success";
		} catch(Exception e) {
			response = "message:failure,data:";
		}
		
		return response;
	}
	
	private String transferRecord(String recordString){
		String response = "";
		List<String> recordParams = Arrays.asList(recordString.trim().split(","));
		Map<String, String> recordParamMap = new HashMap<String, String>();
		for(String item : recordParams){
			List<String> dataParts = Arrays.asList(item.trim().split(":"));
			String label = dataParts.get(0).trim();
			String data = dataParts.get(1).trim();
			recordParamMap.put(label, data);
		}
		
		String recordID = recordParamMap.get("recordID");
		String firstLetterOfLastName = "";
		boolean recordIDExists = (corbaServer.recordStore.findRecordByID(recordID) != null);
		Record record = null;
		if(recordID.startsWith("CR")){
			
			String ID;
			if(!recordIDExists){
				ID = recordID;
			}else{
				ID = corbaServer.generateID("CR");
			}
			
			String fName = recordParamMap.get("firstName");
			String lName = recordParamMap.get("lastName");
			String crimeDesc = recordParamMap.get("crimeDescription");
			String status = recordParamMap.get("status");
			
			record = new CriminalRecord(ID, fName, lName, crimeDesc, status);
			firstLetterOfLastName = lName.substring(0, 1).toUpperCase();

		}else if(recordID.startsWith("MR")){
			
			String ID;
			if(!recordIDExists){
				ID = recordID;
			}else{
				ID = corbaServer.generateID("MR");
			}
			
			String fName = recordParamMap.get("firstName");
			String lName = recordParamMap.get("lastName");
			String description = recordParamMap.get("description");
			String status = recordParamMap.get("status");
			String address = recordParamMap.get("address");
			String lastDate = recordParamMap.get("lastDate");
			String lastLocation = recordParamMap.get("lastLocation");
			
			record = new MissingRecord(ID, fName, lName, description, address, lastDate, lastLocation, status);
			firstLetterOfLastName = lName.substring(0, 1).toUpperCase();
		}
		
		try {
			corbaServer.recordStore.addNewRecord(firstLetterOfLastName.charAt(0), record);
			response = "{code:500, Transferred record., data:" + record + "}";
		} catch (Exception e) {
			response = "{code:-100, Failed to add new record., data:" + record + "}";
		}
		
		return response;
	}

	public String getResponseString() {
		return responseString;
	}
	
	private Map<String, String> processRequestString(String requestStringRaw) {
		String requestString = requestStringRaw.trim();
		
		List<String> items = Arrays.asList(requestString.trim().split("\\,"));
		Map<String, String> params = new HashMap<String, String>();
		
		System.out.println(items);
		
		for(String item : items) {
			List<String> parts = Arrays.asList(item.trim().split("\\:"));
			String key = parts.get(0);
			String value = parts.get(1);
			params.put(key, value);
		}
		
		return params;
	}

}
